package jfood.chef;

import java.util.ArrayList;
import jfood.chef.Stemmer.Stem;
import jfood.ontology.meal.MealOntology;
import jfood.ontology.meal.Result;
import jfood.ontology.meal.ServeMealAction;
import jfood.ontology.meal.ServeMealAction.AnswerType;
import jade.content.Concept;
import jade.content.ContentElement;
import jade.content.lang.Codec.CodecException;
import jade.content.onto.OntologyException;
import jade.content.onto.basic.Action;
import jade.core.behaviours.CyclicBehaviour;
import jade.lang.acl.ACLMessage;
import jfood.ontology.query.AskForMealAction;
import jfood.parser.AlphabetNormalizer;
import jfood.ontology.meal.Meal;

public class WaitForOrdersBehaviour extends CyclicBehaviour {
	/**
	 * 
	 */
	private static final long serialVersionUID = 8133720767189028687L;

	private static Stemmer stemmer_ = new Stemmer();
	
	public WaitForOrdersBehaviour(String databasePath) {
		database_ = new DatabaseReader(databasePath);
	}
	
	public void action() {
		ACLMessage msg = getAgent().receive();
		if (msg == null) {
			block();
			return;
		}

		try {
			ContentElement content = getAgent().getContentManager().extractContent(msg);
			Concept action = ((Action) content).getAction();

			System.out.println(action.getClass());
			
			System.out.println("message received");
			System.out.println(msg.getPerformative());
			switch (msg.getPerformative()) {
			case (ACLMessage.REQUEST):
				if (action instanceof AskForMealAction) {
					AskForMealAction question = (AskForMealAction)((Action)content).getAction();
					System.out.println("waiter ask:" + question.getQuestion());
					HandleResult handleResult = handleQuestion(question.getQuestion());
					
					ACLMessage reply = msg.createReply();
					reply.setOntology(MealOntology.NAME);
					reply.setPerformative(ACLMessage.INFORM);
					
					ServeMealAction response = new ServeMealAction();
					response.setType(AnswerType.NOTHING);
					if(handleResult.searched == ToSearch.RECIPE)
					{
						response.setAskFor(handleResult.meal);
						response.setType(AnswerType.RECIPE);
					}
					else if(handleResult.searched == ToSearch.MEAL_PREPOSITONS)
					{
						response.setResults(handleResult.mealList);
						response.setType(AnswerType.PREPOSITIONS);
					}
					
					Action actOperator = new Action(msg.getSender(), response);
					
					try {
						myAgent.getContentManager().fillContent(reply,actOperator);
					} catch (CodecException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					} catch (OntologyException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					getAgent().send(reply);
				}
			}
		} catch (Exception ex) {
			ex.printStackTrace();
		}
	}
	
	public enum TokenType
	{
		UKNOWN,
		MEAL,
		MEAL_STEM,
		INGREDIENT,
		INGREDENT_STEM,
		MEAL_PART,
		MEAL_STEM_PART,
		INGREDIENT_PART,
		INGREDIENT_STEM_PART
	}
	public enum ToSearch
	{
		UNKNOWN,
		RECIPE,
		MEAL_PREPOSITONS,
	}
	
	public class Token
	{
		public Token(TokenType tokenType, String token)
		{
			type_ = tokenType;
			name_ = token;
		}
		public TokenType getTokenType()
		{
			return type_;
		}
		public String getTokenName()
		{
			return name_;
		}
		public void setTokenType(final TokenType tokenType)
		{
			type_ = tokenType;
		}
		public void setTokenName(final String tokenName)
		{
			name_ = tokenName;
		}
		
		public TokenType type_;
		public String name_;
	}	
	private class HandleResult
	{
		ArrayList<Meal> mealList;
		Meal meal;
		ToSearch searched;
	}
	protected HandleResult handleQuestion(String question)
	{
		ArrayList<Stem> stems = stemmer_.stemSentenceWithForbiddens(question, false);
		
		for(Stem s:stems)
		{
			System.out.println(s.toString());
		}
		
		ArrayList<Token> tokens = prepareStemTokens(stems);
		
		System.out.println("TOKEN");
		for(Token t: tokens)
		{
			System.out.println(t.type_);
			System.out.println(t.name_);
		}
		
		ToSearch toSearch = ToSearch.UNKNOWN;
		ArrayList<Token> toFind = new ArrayList<Token>();
		 
		for(Token t: tokens)
		{
			if(t.type_ == TokenType.MEAL_STEM)
			{
				toFind.clear();
				toFind.add(t);
				toSearch = ToSearch.RECIPE;
				break;
			}
			else if(t.type_ == TokenType.INGREDENT_STEM)
			{
				toFind.add(t);
				toSearch = ToSearch.MEAL_PREPOSITONS;
			}
		}
		
		System.out.println("TO FIND");
		for(Token t: toFind)
		{
			System.out.println(t.type_);
			System.out.println(t.name_);
		}
		
		HandleResult handleResult = new HandleResult();
		handleResult.searched = toSearch;
		if(toSearch == ToSearch.RECIPE)
		{
			String mealName = database_.getMealNameByStems(toFind.get(0).getTokenName());
			handleResult.meal = database_.getMeal(mealName);
		}
		else if(toSearch == ToSearch.MEAL_PREPOSITONS)
		{
			ArrayList<String> ingredientsStems = new ArrayList<String>();
			for(Token t: toFind)
			{
				ingredientsStems.add(t.getTokenName());
			}
			handleResult.mealList = database_.getMealWithGivenIngredientsStem(ingredientsStems);
		}

		return handleResult;
	}
	private ArrayList<Token> prepareTokens(final ArrayList<String> tokensNames)
	{
		String buffer = "";
		ArrayList<Token> tokens = new ArrayList<Token>();
		for(String token: tokensNames)
		{
			System.out.println(token);
			token = AlphabetNormalizer.unAccent(token);
			token = token.toLowerCase();
			
			buffer = buffer + token;
			Result result = database_.checkElement(token);
			if(result.isMeal)
			{
				tokens.add(new Token(TokenType.MEAL, buffer));
				buffer = new String("");
			}
			else if(result.isIngredient)
			{
				tokens.add(new Token(TokenType.INGREDIENT, buffer));
				buffer = new String("");
			}
			else if(result.isPartOfIngredient)
			{
				
			}
			else if(result.isPartOfMeal)
			{
			}
		}
		return tokens;
	}
	private ArrayList<Token> prepareStemTokens(final ArrayList<Stem> stems)
	{
		String buffer = "";
		ArrayList<Token> tokens = new ArrayList<Token>();
		for(Stem stem: stems)
		{
			String stemName = stem.getStem();
			System.out.println(stemName);
			
			stemName = AlphabetNormalizer.unAccent(stemName);
			stemName = stemName.toLowerCase();
			buffer = buffer + stemName + " ";			

			System.out.println(buffer);
			
			Result result = database_.checkElementWithStems(buffer);
			
//			System.out.println(result.toString());
			
			if(result.isMealStem)
			{
				tokens.add(new Token(TokenType.MEAL_STEM, buffer));
				buffer = "";
			}
			else if(result.isPartOfMealStem)
			{
			}
			else if(result.isIngredientStem)
			{
				System.out.println("isIngredientStem");
				tokens.add(new Token(TokenType.INGREDENT_STEM, buffer));
				buffer = "";
			}
			else if(result.isPartOfIngredientStem)
			{
			}
			
			else
			{
				buffer = "";
			}

		}
		return tokens;
	}

	DatabaseReader database_;
}
